package com.allwees.data.dataport.common.api;

import com.allwees.bs.core.modelbase.exception.BusinessException;
import com.allwees.bs.core.modelbase.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 通用的异常错误处理
 *
 * @author jy2016
 */
@ControllerAdvice
@Slf4j
public abstract class BaseApi {

    protected void printErrMessage(String path, String message) {
        log.error("path : {}", path);
        log.error("message : {}", message);
    }

    @ExceptionHandler({Exception.class})
    @ResponseBody
    public R formatErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        log.error("服务器异常", e);
        String path = req.getRequestURI();
        String msg = e.getMessage();
        printErrMessage(path, msg);

        Map<String, String> errorMap = new HashMap<>(2);
        errorMap.put("exception", msg);
        errorMap.put("path", path);

        return R.error(-10,"server error").data(errorMap);
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public R formatErrorHandler(HttpServletRequest req, MethodArgumentNotValidException e) throws Exception {
        log.error("参数解析异常");
        String path = req.getRequestURI();
        String msg = "";

        List<String> errors = new ArrayList<>();
        if (e.getBindingResult().hasErrors()) {
            for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
                errors.add(fieldError.getField() + " " + fieldError.getDefaultMessage());
            }
        }
        msg = StringUtils.join(errors, ",");
        printErrMessage(path, msg);

        Map<String, String> errorMap = new HashMap<>(2);
        errorMap.put("exception", "");
        errorMap.put("path", path);

        return R.error(-10,msg).data(errorMap);
    }

    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseBody
    public R formatErrorHandler(HttpServletRequest req, ConstraintViolationException e) throws Exception {
        log.error("控制器参数解析异常");
        String path = req.getRequestURI();
        String msg = "";
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
        List<String> errors = new ArrayList<>();
        while (iterator.hasNext()) {
            ConstraintViolation<?> cvl = iterator.next();
            errors.add(cvl.getMessage());
        }
        msg = StringUtils.join(errors, ",");
        printErrMessage(path, msg);

        Map<String, String> errorMap = new HashMap<>(2);
        errorMap.put("exception", "");
        errorMap.put("path", path);

        return R.error(-10, msg).data(errorMap);
    }

    @ExceptionHandler({HttpMessageNotReadableException.class})
    @ResponseBody
    public R formatErrorHandler(HttpServletRequest req, HttpMessageNotReadableException e) throws Exception {
        String msg = "Json body参数解析异常";
        log.error(msg, e);
        String path = req.getRequestURI();
        printErrMessage(path, msg);

        Map<String, String> errorMap = new HashMap<>(2);
        errorMap.put("exception", e.getMessage());
        errorMap.put("path", path);

        return R.error(-10, msg).data(errorMap);
    }

    @ExceptionHandler({BusinessException.class})
    @ResponseBody
    public R formatErrorHandler(HttpServletRequest req, BusinessException e) throws Exception {
        log.error("业务异常:" + e.getCode() + " " + e.getMsg(), e);
        String path = req.getRequestURI();
        String msg = e.getMsg();
        printErrMessage(path, msg);

        Map<String, String> errorMap = new HashMap<>(2);
        errorMap.put("exception", e.getMsg());
        errorMap.put("path", req.getRequestURI());

        return R.error(-10, msg).data(errorMap);
    }
}
